package server

import (
	"context"
	"fmt"
	"longmen/server/pkg/common/helper/const"
	time2 "longmen/server/pkg/common/helper/timehelper"
	"longmen/server/pkg/common/helper/util"
	"longmen/server/pkg/db/mysql/db_main"
	"longmen/server/pkg/db/mysql/models/models_main"
	"longmen/server/pkg/protobuf"
	"time"

	"github.com/jinzhu/copier"
	"github.com/labstack/echo/v4"
	"longmen/server/pkg/common/api_models"
)

/**
 * @author Aaron
 * @description Server层 获取用户的任务列表，和完成情况
 * @createTime 9:39 2022/5/17
 **/
func (s *Server) GetTaskList(ctx context.Context, req *protobuf.GetTaskListReq) (*protobuf.GetTaskListRespList, error) {
	var (
		err                         error
		taskIds                     []uint8
		taskListResp                []*protobuf.GetTaskListResp
		rewardList                  []*protobuf.RewardByIds
		taskList                    []*api_models.Task
		userTaskList                []*models_main.UserTask
		secondStamp                       = time2.GetTimeStamp(1)
		nMaxCheckinDays             uint8 = 1 //签到任务中配置的最高天数是多少，达到了这一天后天数可以从头开始算
		iYesterdayChekckinFrequency uint8 = 0 //昨天的签到是第几天的
		iTodayChekckinFrequency     uint8 = 0 //今天签到是第几天的

	)
	checkInTaskMap := make(map[int]uint8)
	if taskList, err = db_main.GetTaskListParam(nil, int(req.Page), int(req.Size)); err != nil {
		return nil, err
	}

	for i := range taskList {
		//限时任务判断
		if _const.TaskType(taskList[i].Type) == _const.LIMIT_TIME_TASK &&
			(secondStamp < taskList[i].BeginTime.Unix() || secondStamp > taskList[i].EndTime.Unix()) {
			continue
		}
		if _const.TaskType(taskList[i].Type) == _const.CHECK_IN_TASK {
			checkInTaskMap[taskList[i].Id] = taskList[i].Frequency //记录这个任务是签到任务，且要几天
			if taskList[i].Frequency > nMaxCheckinDays {
				nMaxCheckinDays = taskList[i].Frequency //记录世界上最多的签到天数
			}
		}
		taskIds = append(taskIds, uint8(taskList[i].Id))
		des := new(protobuf.GetTaskListResp)
		if err = copier.Copy(des, taskList[i]); err != nil {
			return nil, fmt.Errorf("%s %s", util.Convert2(), err.Error())
		}
		taskListResp = append(taskListResp, des)
	}

	// 批量领取任务奖励
	if rewardList, err = s.getTaskListRewardByIds(taskIds); err != nil {
		return nil, err
	}

	if userTaskList, err = db_main.GetUserTasksParam(
		echo.Map{"uid": req.Uid},
		"",
		0,
		255, //限制条数
	); err != nil {
		return nil, err
	}

	for _, ut := range userTaskList {
		if uint32(ut.IsReceived) > 0 { //签到任务
			if frequencyOfThisTask, ok := checkInTaskMap[int(ut.TaskId)]; ok {
				if time2.TimeInNDaysAgo(ut.DoAt, 1) { //这个时间是昨天的吗
					iYesterdayChekckinFrequency = frequencyOfThisTask //昨天完成的是连续几天
				} else {
					if time2.TimeInNDaysAgo(ut.DoAt, 0) { //这个时间是今天的吗
						iTodayChekckinFrequency = frequencyOfThisTask
					}
				}
			}
			//签到任务什么时候能做呢？如果iYesterday == 昨天完成的签到任务，则frenquency == iYesterday +1的任务是可以完成的
			//如果昨天没有完成任何签到任务，那么能做第一天的
			//如果昨天的签到天数达到了最高天数
		}
	}
	if iYesterdayChekckinFrequency == nMaxCheckinDays {
		iYesterdayChekckinFrequency = 0 //如果已经达到最高天数，就归0从头开始
	}
	for _, respNode := range taskListResp {
		for _, reward := range rewardList {
			if uint64(reward.TaskId) != respNode.Id {
				continue
			}

			if err = copier.Copy(respNode, reward); err != nil {
				return nil, fmt.Errorf("%s %s", util.Convert2(), err.Error())
			}
		}

		if req.Uid == 0 {
			continue
		}

		for _, ut := range userTaskList {
			if uint64(ut.TaskId) != respNode.Id {
				continue
			}
			if uint32(ut.Stage) > respNode.Frequency {
				respNode.Stage = respNode.Frequency
			}
			if respNode.Type == 0 { //日常任务
				if time2.TimeInSameDay(ut.DoAt, time.Now()) {
					respNode.Stage = uint32(ut.Stage)
					respNode.IsReceived = uint32(ut.IsReceived)
				} else { //上次任务时间不是同一天，那可以做的
					respNode.Stage = 0
					respNode.IsReceived = 0
				}
			} else if respNode.Type == 1 { //新手任务
				respNode.Stage = uint32(ut.Stage)
				respNode.IsReceived = uint32(ut.IsReceived)
			} else if respNode.Type == uint32(_const.CHECK_IN_TASK) { //签到任务
				//如果当前任务要的天数==昨天完成的天数+1，那就可以做
				if iTodayChekckinFrequency != 0 {
					if respNode.Frequency <= uint32(iTodayChekckinFrequency) {
						respNode.Stage = uint32(ut.Stage)
						respNode.IsReceived = uint32(ut.IsReceived)
					}
				} else { //今天没有完成签到
					if respNode.Frequency == uint32(iYesterdayChekckinFrequency)+1 {
						respNode.Stage = 0
						respNode.IsReceived = 0
					} else if respNode.Frequency <= uint32(iYesterdayChekckinFrequency) {
						respNode.Stage = uint32(ut.Stage)
						respNode.IsReceived = 1 //已领取
					}
				}
			} //end for这里是有记录的
		}
	}

	for i := 0; i < len(taskListResp)-1; i++ {
		for j := 0; j < len(taskListResp)-1-i; j++ {
			if taskListResp[j].IsReceived > taskListResp[j+1].IsReceived {
				taskListResp[j], taskListResp[j+1] = taskListResp[j+1], taskListResp[j]
			}
		}
	}

	return &protobuf.GetTaskListRespList{
		GetTaskListResp: taskListResp,
	}, nil /**/
}

/*
*
  - @author Aaron
  - @description 获取用户领取奖励记录
  - @createTime 10:19 2022/5/24
    查询接口

*
*/
func (s *Server) GetRecord(ctx context.Context, req *protobuf.UidReq) (*protobuf.GetRecordRespList, error) {
	var taskIds []uint8
	respList := make([]*protobuf.GetRecordResp, 0)
	utList, err := db_main.GetRecord(int(req.Uid))
	if err != nil {
		return nil, err
	}
	for _, ut := range utList {
		taskIds = append(taskIds, ut.TaskId)
	}
	if len(taskIds) <= 0 {
		return &protobuf.GetRecordRespList{
			GetRecordResp: respList,
		}, nil
	}
	taskList, err := db_main.GetTaskListByIds(taskIds)
	if err != nil {
		return nil, err
	}
	rewardList, err := s.getTaskListRewardByIds(taskIds)
	if err != nil {
		return nil, err
	}
	for _, ut := range utList {
		resp := &protobuf.GetRecordResp{}
		for _, task := range taskList {
			if int(ut.TaskId) == task.Id {
				resp.Name = task.Name
			}
		}
		for _, r := range rewardList {
			if uint32(ut.TaskId) == r.TaskId {
				err := copier.Copy(resp, r)
				if err != nil {
					return nil, fmt.Errorf("%s%s", util.Convert2(), err.Error())
				}
				resp.Id = uint64(ut.Id)
			}
		}
		resp.CreateTime = ut.CreatedAt.Unix()
		respList = append(respList, resp)
	}
	return &protobuf.GetRecordRespList{
		GetRecordResp: respList,
	}, nil
}

/*
*

  - @author Aaron

  - @description  Server层 根据任务ID获取任务奖励

  - @createTime 11:08 2022/5/18

    *
*/
func (s *Server) GetTaskRewardById(id uint8) (*protobuf.Reward, error) {
	resp := &protobuf.Reward{}
	TaskRewardList, err := db_main.GetTaskRewardById2(id)
	if err != nil {
		return nil, err
	}
	for _, reward := range TaskRewardList {
		switch _const.RewardType(reward.RewardType) {
		case _const.REWARD_TYPE_DIAMOND:
			resp.Diamond = reward.Quantity //奖励用户克拉
		case _const.REWARD_TYPE_EXP:
			resp.Exp = reward.Quantity //奖励用户经验
		case _const.REWARD_TYPE_GOLD:
			resp.Gold = reward.Quantity //奖励用户鹰钻
		case _const.REWARD_TYPE_GIFT:
			resp.Gift = append(resp.Gift, &protobuf.Gift{
				Id:       uint32(reward.GiftId),
				Title:    reward.Title,
				Icon:     reward.Icon,
				Quantity: reward.Quantity,
			})
		}
	}
	if len(resp.Gift) == 0 {
		resp.Gift = []*protobuf.Gift{}
	}
	return resp, nil
}

/*
*
* @author Aaron
* @description Server层 根据任务ID数组批量领取获取任务奖励
* @createTime 13:55 2022/5/18
传入一些任务id，返回
*
*/
func (s *Server) getTaskListRewardByIds(ids []uint8) ([]*protobuf.RewardByIds, error) {
	var (
		err            error
		rewards        []*protobuf.RewardByIds
		taskRewardList []*api_models.GetTaskRewardList
		setRewards     = func(reward *protobuf.RewardByIds, TaskReward *api_models.GetTaskRewardList) {
			// 0-经验,1-gold鹰钻,2-diamond克拉,3-礼物, 4-道具
			switch _const.RewardType(TaskReward.RewardType) {
			case _const.REWARD_TYPE_DIAMOND:
				reward.Diamond = TaskReward.Quantity //奖励用户克拉
			case _const.REWARD_TYPE_EXP:
				reward.Exp = TaskReward.Quantity //奖励用户经验
			case _const.REWARD_TYPE_GOLD:
				reward.Gold = TaskReward.Quantity //奖励用户鹰钻
			case _const.REWARD_TYPE_GIFT:
				reward.Gift = append(reward.Gift, &protobuf.Gift{
					Id:       uint32(TaskReward.GiftId),
					Title:    TaskReward.Title,
					Icon:     TaskReward.Icon,
					Quantity: TaskReward.Quantity,
				})
			}
		}
		finAndSetRewards = func(TaskReward *api_models.GetTaskRewardList) (flag bool) {
			for _, reward := range rewards {
				if int(reward.TaskId) == TaskReward.TaskId {
					setRewards(reward, TaskReward)
					flag = true
					break
				}
			}
			return flag
		}
	)

	if len(ids) == 0 {
		return []*protobuf.RewardByIds{}, nil
	}

	// 获取任务奖励
	//if taskRewardList, err = repository.GetTaskRewardListByIds(ids); err != nil {
	if taskRewardList, err = db_main.GetTaskRewardListByIds2(ids); err != nil { //todo检查数据
		return nil, err
	}

	//【奖励类型】判断
	for _, TaskReward := range taskRewardList {
		if finAndSetRewards(TaskReward) {
			continue
		}

		reward := &protobuf.RewardByIds{}
		setRewards(reward, TaskReward)

		reward.TaskId = uint32(TaskReward.TaskId)
		if len(reward.Gift) == 0 {
			reward.Gift = []*protobuf.Gift{}
		}
		rewards = append(rewards, reward)
	}
	return rewards, nil
}
